<?php
/**
 * 库存业务方法
 *
 * User: sickeeer
 * Date: 2018/5/30
 * Time: 13:01
 */

namespace App\Models;
use Encore\Admin\Facades\Admin;
use App\Admin\Controllers\HelpersController;

class InventoryFunc
{
    public $id;
    public $name;
    public $checking_type;
    public $checking_detail_type;
    public $checking_detail_io_type;
    public $allowName = ['purchase','order','in_transfer','out_transfer'];
    function __construct($name,$id)
    {
        $name = strtolower($name);
        if(!in_array($name,$this->allowName)) {
            throw new \Exception("system error, unknown name for __construct");
        }
        $this->id = $id;
        $this->name = $name;
        /*
         * checking_detail_type
         *
            '1' => '出库',
            '2' => '入库',
            '3' => '出库锁定',
            '4' => '入库在途',
            '5' => '调拨锁定',
            '6' => '调拨在途',
            '103' => '出库锁定释放',
            '104' => '入库在途释放',
            '105' => '调拨锁定释放',
            '106' => '调拨在途释放',

         *
         * checking_type
         *
            1. 锁定
            2. 在途
         */
        switch ($name){
            case "purchase":
                $this->checking_detail_type = 4;
                $this->checking_type = 2;
                $this->checking_detail_io_type = 104;
            break;
            case "order":
                $this->checking_detail_type = 3;
                $this->checking_type = 1;
                $this->checking_detail_io_type = 103;
            break;
            case "in_transfer":
                $this->checking_detail_type = 4;
                $this->checking_type = 2;
                $this->checking_detail_io_type = 106;
            break;
            case "out_transfer":
                $this->checking_detail_type = 3;
                $this->checking_type = 1;
                $this->checking_detail_io_type = 105;
            break;
        }
    }

    /**
     * 插入仓储详情表以及仓库明细表
     *
     * @param
     * @return $this
     */
    public function insertInventoryChecking()
    {
        $details = \DB::table($this->name.'_detail')
            ->select($this->name.'_detail.*',$this->name.'.warehouse_id')
            ->leftjoin($this->name,($this->name).'.id','=',($this->name).'_detail.'.($this->name.'_id'))
            ->where($this->name.'_id',$this->id)
            ->get();

        $arrs =[];
        foreach ($details as  $detail) {
            $arr = [
                'sku_id' => $detail->sku_id,
                'type' => $this->checking_detail_type,
                'num' => $detail->num,
                'size' => $detail->size,
                'operater_id' => Admin::user()->username,
                'checking_ASN' => $detail->{$this->name."_id"},
                'grade' => $detail->grade,
                'thick' => $detail->thick,
                'origin' => $detail->origin,
                'colour' => $detail->colour,
                'avg_size' => $detail->avg_size,
                'min_size' => $detail->min_size,
                'grade_o' => $detail->grade,
                'thick_o' => $detail->thick,
                'origin_o' => $detail->origin,
                'colour_o' => $detail->colour,
                'avg_size_o' => $detail->avg_size,
                'min_size_o' => $detail->min_size,
                'created_at' => date('Y-m-d H:i:s')
            ];
            $inventory_checking = [
                'sku_id' =>$detail->sku_id,
                'type'=>$this->checking_type,
                'warehouse_id'=>$detail->warehouse_id,
                'grade' => $detail->grade,
                'thick' => $detail->thick,
                'origin' => $detail->origin,
                'colour' => $detail->colour,
                'avg_size' => $detail->avg_size,
                'min_size' => $detail->min_size,
            ];
            if (\DB::table('inventory_checking')->where($inventory_checking)->count()){
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size+'.$detail->size),'num'=> \DB::raw('num+'.$detail->num)]);
            }else{
                $insert = $inventory_checking;
                $insert['size'] = $detail->size;
                $insert['num'] = $detail->num;
                \DB::table('inventory_checking')->insert($insert);
            }
            array_push($arrs,$arr);
        }
        \DB::table('inventory_checking_detail')->insert($arrs);
        return $this;
    }

    /**
     * 插入审核详单
     *
     * @param $input
     * @return $this
     */
    public function insertBillsChecking($input)
    {
        \DB::table('bills_checking_detail')->insert([
            'operater_id'=>Admin::user()->username,
            'created_at'=>date('Y-m-d H:i:s'),
            'data'=>json_encode($input),
            'checking_ASN'=>$this->id
        ]);
        return $this;
    }

    /**
     *  出入库逻辑  sql 顺序不可随意调换
     *
     * @param $input
     * @return $this
     */
    public function insertInventoryAndCheckingOne($input){
        $info = \DB::table($this->name.'_detail')
            ->select($this->name.'_detail.*',$this->name.'.warehouse_id')
            ->leftjoin($this->name,($this->name).'.id','=',($this->name).'_detail.'.($this->name.'_id'))
            ->where($this->name.'_detail.id',$this->id)
            ->first();
        if($this->name == "purchase"){
            $bid=HelpersController::getId('batch_id','B');
        }else{
            $input = array_merge( $input, get_object_vars(\DB::table('inventory')->find($input['inventory_sn'])) );
            $bid=$input['inventory_id'];
        }
        $batchattribute = [
            'grade'=>$input['grade'],
            'thick'=>$input['thick'],
            'origin'=>$input['origin'],
            'colour'=>$input['colour'],
            'avg_size'=>$input['avg_size'],
            'min_size'=>$input['min_size']
        ];
        $batchattribute_o = [
            'grade_o' => $info->grade,
            'thick_o' => $info->thick,
            'origin_o' => $info->origin,
            'colour_o' => $info->colour,
            'avg_size_o' => $info->avg_size,
            'min_size_o' => $info->min_size
        ];

        \DB::table('inventory_checking_detail')->insert([
            array_merge([
                'sku_id'=>$input['sku_id'],
                'type'=>($this->name == "purchase"?2:1),
                'num'=>$input['arrive_num'],
                'size' => $input['arrive_size'],
                'operater_id'=>Admin::user()->username,
                'checking_ASN'=>$input[$this->name.'_id'],
                'inventory_id'=>$bid,
                'created_at'=>date('Y-m-d H:i:s')
            ],$batchattribute,$batchattribute_o),
            array_merge([
                'sku_id'=>$input['sku_id'],
                'type'=>$this->checking_detail_io_type,
                'num'=>0-$input['arrive_num'],
                'size' =>0- $input['arrive_size'],
                'operater_id'=>Admin::user()->username,
                'checking_ASN'=>$input[$this->name.'_id'],
                'inventory_id'=>$bid,
                'created_at'=>date('Y-m-d H:i:s')
            ],$batchattribute,$batchattribute_o)
        ]);
        $inventory_checking =[
            'sku_id' =>$info->sku_id,
            'type'=>$this->checking_type,
            'warehouse_id'=>$info->warehouse_id,
            'grade' => $info->grade,
            'thick' => $info->thick,
            'origin' => $info->origin,
            'colour' => $info->colour,
            'avg_size' => $info->avg_size,
            'min_size' => $info->min_size
        ];
        if($this->name == "purchase"){
            \DB::table('inventory')->insert(
                array_merge([
                    'currency' => $input['currency'],
                    'inventory_id' =>$bid,
                    'over_num' => $input['arrive_num'],
                    'over_size' => $input['arrive_size'],
                    'sku_id' => $input['sku_id'],
                    'warehouse_zone_id'=>$input['warehouse_zone_id'],
                    'warehouse_location_id'=>$input['warehouse_location_id'],
                    'warehouse_id'=>$input['warehouse_id'],
                    'price' => $input['price'],
                    'created_at'=>date('Y-m-d H:i:s')
                ],$batchattribute)
            );
            if($input['in_state'] == "PART_IN"){
                // 部分入库
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size-'.$input['arrive_size']),'num'=> \DB::raw('num-'.$input['arrive_num'])]);
            }elseif($input['in_state'] == "ALL_IN"){
                $hadIn = \DB::table('inventory_checking_detail')->where(array_merge($batchattribute_o,['sku_id'=>$info->sku_id, 'checking_ASN'=>$info->purchase_id,'type'=>2]))->select(\DB::raw('sum(size) as size_all'),\DB::raw('sum(num) as num_all'))->first();
                // 全部入库 需要计算 释放全部在途 当前数值 - 单据数量 + 实际数量 = 真实释放
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size+'.($hadIn->size_all-$input['arrive_size']).'-'.$info->size),'num'=> \DB::raw('num+'.($hadIn->num_all-$input['arrive_num']).'-'.$info->num)]);
            }
        }else{
            \DB::table('inventory')
                ->where('id',$input['inventory_sn'])
                ->update(['over_size'=> \DB::raw('over_size-'.$input['arrive_size']),'over_num'=> \DB::raw('over_num-'.$input['arrive_num'])]);
            if($input['out_state'] == "PART_OUT"){
                // 部分出库
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size-'.$input['arrive_size']),'num'=> \DB::raw('num-'.$input['arrive_num'])]);
            }elseif($input['out_state'] == "ALL_OUT"){
                $hadOut = \DB::table('inventory_checking_detail')->where(array_merge($batchattribute_o,['sku_id'=>$info->sku_id, 'checking_ASN'=>$info->order_id,'type'=>1]))->select(\DB::raw('sum(size) as size_all'),\DB::raw('sum(num) as num_all'))->first();
                // 全部出库 需要计算 释放全部锁定 当前数值 - 单据数量 + 实际数量 = 真实释放
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size+'.($hadOut->size_all-$input['arrive_size']).'-'.$info->size),'num'=> \DB::raw('num+'.($hadOut->num_all-$input['arrive_num']).'-'.$info->num)]);
            }
        }
        return $this;
    }

    /**
     * 调拨出入库逻辑  sql 顺序不可随意调换
     *
     * @param $input
     * @return $this
     */
    public function insertTransferInventoryAndCheckingOne($input){
        $warehouse = ($this->name == "out_transfer")?"out_warehouse_id":"in_warehouse_id";
        $info = \DB::table($this->name.'_bill_detail')
            ->select($this->name.'_bill_detail.*','transfer_bill.'.$warehouse)
            ->leftjoin('transfer_bill','transfer_bill.id','=',($this->name).'_bill_detail.transfer_bill_id')
            ->where($this->name.'_bill_detail.id',$this->id)
            ->first();
        $input = array_merge( $input, get_object_vars(\DB::table('inventory')->select('inventory.grade','inventory.thick','inventory.origin','inventory.colour','inventory.avg_size','inventory.min_size','inventory.price')->find($input['inventory_sn'])) );
        $bid=$input['inventory_id'];
        $batchattribute = [
            'grade'=>$input['grade'],
            'thick'=>$input['thick'],
            'origin'=>$input['origin'],
            'colour'=>$input['colour'],
            'avg_size'=>$input['avg_size'],
            'min_size'=>$input['min_size']
        ];
        $batchattribute_o = [
            'grade_o'=>$input['grade'],
            'thick_o'=>$input['thick'],
            'origin_o'=>$input['origin'],
            'colour_o'=>$input['colour'],
            'avg_size_o'=>$input['avg_size'],
            'min_size_o'=>$input['min_size']
        ];
        \DB::table('inventory_checking_detail')->insert([
            array_merge([
                'sku_id'=>$input['sku_id'],
                'type'=>($this->name == "in_transfer"?2:1),
                'num'=>$input['arrive_num'],
                'size' => $input['arrive_size'],
                'operater_id'=>Admin::user()->username,
                'checking_ASN'=>$info->transfer_bill_id,
                'inventory_id'=>$bid,
                'created_at'=>date('Y-m-d H:i:s')
            ],$batchattribute,$batchattribute_o),
            array_merge([
                'sku_id'=>$input['sku_id'],
                'type'=>$this->checking_detail_io_type,
                'num'=>0-$input['arrive_num'],
                'size' =>0- $input['arrive_size'],
                'operater_id'=>Admin::user()->username,
                'checking_ASN'=>$info->transfer_bill_id,
                'inventory_id'=>$bid,
                'created_at'=>date('Y-m-d H:i:s')
            ],$batchattribute,$batchattribute_o)
        ]);
        $inventory_checking =array_merge([
            'sku_id' =>$info->sku_id,
            'type'=>$this->checking_type,
            'warehouse_id'=>$info->$warehouse,
        ],$batchattribute);
        if($this->name == "in_transfer"){
            $where = ['inventory_id' => $input['inventory_id'], 'warehouse_id' => $input['warehouse_id'], 'warehouse_zone_id' => $input['warehouse_zone_id'], 'warehouse_location_id'=>$input['warehouse_location_id'],'price'=>$input['price']];
            if (\DB::table('inventory')->where($where)->count()) {
                \DB::table('inventory')->where($where)->update(['over_size' => \DB::raw('over_size+' . $input['arrive_size']), 'over_num' => \DB::raw('over_num+' . $input['arrive_num'])]);
            }else {
                \DB::table('inventory')->insert(
                    array_merge([
                        'inventory_id' => $bid,
                        'over_num' => $input['arrive_num'],
                        'over_size' => $input['arrive_size'],
                        'sku_id' => $input['sku_id'],
                        'warehouse_zone_id' => $input['warehouse_zone_id'],
                        'warehouse_location_id' => $input['warehouse_location_id'],
                        'warehouse_id' => $input['warehouse_id'],
                        'price' => $input['price'],
                        'created_at' => date('Y-m-d H:i:s')
                    ], $batchattribute)
                );
            }
            if($input['in_state'] == "PART_IN"){
                // 部分入库
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size-'.$input['arrive_size']),'num'=> \DB::raw('num-'.$input['arrive_num'])]);
            }elseif($input['in_state'] == "ALL_IN"){
                $hadIn = \DB::table('inventory_checking_detail')->where(array_merge($batchattribute_o,['sku_id'=>$info->sku_id, 'checking_ASN'=>$info->transfer_bill_id,'type'=>2]))->select(\DB::raw('sum(size) as size_all'),\DB::raw('sum(num) as num_all'))->first();
                // 全部入库 需要计算 释放全部在途 当前数值 - 单据数量 + 实际数量 = 真实释放
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size+'.($hadIn->size_all-$input['arrive_size']).'-'.$info->size),'num'=> \DB::raw('num+'.($hadIn->num_all-$input['arrive_num']).'-'.$info->num)]);
            }
        }else{
            \DB::table('inventory')
                ->where('id',$input['inventory_sn'])
                ->update(['over_size'=> \DB::raw('over_size-'.$input['arrive_size']),'over_num'=> \DB::raw('over_num-'.$input['arrive_num'])]);
            if($input['out_state'] == "PART_OUT"){
                // 部分出库
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size-'.$input['arrive_size']),'num'=> \DB::raw('num-'.$input['arrive_num'])]);
            }elseif($input['out_state'] == "ALL_OUT"){
                $hadOut = \DB::table('inventory_checking_detail')->where(array_merge($batchattribute_o,['sku_id'=>$info->sku_id, 'checking_ASN'=>$info->transfer_bill_id,'type'=>1]))->select(\DB::raw('sum(size) as size_all'),\DB::raw('sum(num) as num_all'))->first();
                // 全部出库 需要计算 释放全部锁定 当前数值 - 单据数量 + 实际数量 = 真实释放
                \DB::table('inventory_checking')->where($inventory_checking)->update(['size'=> \DB::raw('size+'.($hadOut->size_all-$input['arrive_size']).'-'.$info->size),'num'=> \DB::raw('num+'.($hadOut->num_all-$input['arrive_num']).'-'.$info->num)]);
            }
        }
        return $this;
    }
}